#include "preHeader.h"
#include "SceneMgr.h"

SceneMgr::SceneMgr()
{
}

SceneMgr::~SceneMgr()
{
	for (auto& pair : m_scenes) {
		delete pair.second;
	}
}

Scene* SceneMgr::GetScene(const std::string& sceneDir)
{
	std::shared_lock<std::shared_mutex> lock(m_sceneMutex);
	auto itr = m_scenes.find(sceneDir);
	return itr != m_scenes.end() ? itr->second : NULL;
}

Scene* SceneMgr::CreateAndGetScene(const std::string& sceneDir)
{
	auto pScene = GetScene(sceneDir);
	if (pScene != NULL) {
		return pScene;
	}

	bool isNewScene = false;
	do {
		std::lock_guard<std::mutex> lock(m_loadingMutex);
		std::tie(std::ignore, isNewScene) = m_sceneLoading.insert(sceneDir);
	} while (0);
	if (isNewScene) {
		Scene* pScene = new Scene;
		if (!pScene->Init(sceneDir)) {
			ELOG("Init scene `%s` failed.", sceneDir.c_str());
		}
		do {
			std::lock_guard<std::shared_mutex> lock(m_sceneMutex);
			m_scenes.emplace(sceneDir, pScene);
		} while (0);
		m_loadingCV.notify_all();
		return pScene;
	}

	fakelock lock;
	const std::chrono::milliseconds duration(100);
	while (m_loadingCV.wait_for(lock, duration), true) {
		if ((pScene = GetScene(sceneDir)) != NULL) {
			return pScene;
		}
	}

	return NULL;
}
